/* eslint-disable prefer-destructuring */
import {
  Scene,
  Vector3,
  MeshBuilder,
  Color3,
  Color4,
  Mesh,
  Texture,
  StandardMaterial,
  Vector4
} from 'babylonjs'
import earcut from 'earcut'
import fenceGreyPic from '@/assets/fence/fenceGrey.png'
import fenceBlackPic from '@/assets/fence/fenceBlack.png'
import fenceYellowPic from '@/assets/fence/fenceYellow.png'
import fenceBluePic from '@/assets/fence/fenceBlue.png'
import fenceWhitePic from '@/assets/fence/fenceWhite.png'
import fenceRedPic from '@/assets/fence/fenceRed.png'
import bLockPic from '@/assets/b-lock.png'

import wheelPic from '@/assets/wheel-r.png'

const fixRadian = (start: number[], angle: number, distance: number) => {
  let radian = 0
  let points = start
  let lineAngle = angle
  if (angle < -180) angle += 360

  if (angle >= -22.5 && angle <= 22.5) {
    lineAngle = 0
    points = [start[0] + distance, start[1]]
  } else if (angle >= 22.5 && angle <= 67.5) {
    lineAngle = 45
    radian = (45 * Math.PI) / 180
    points = [start[0] + Math.sin(radian) * distance, start[1] - Math.cos(radian) * distance]
  } else if (angle >= 67.5 && angle <= 112.5) {
    lineAngle = 90
    points = [start[0], start[1] - distance]
  } else if (angle >= 112.5 && angle <= 157.5) {
    lineAngle = 135
    radian = (135 * Math.PI) / 180
    points = [start[0] - Math.sin(radian) * distance, start[1] + Math.cos(radian) * distance]
  } else if (angle >= 157.5 || angle <= -157.5) {
    lineAngle = 180
    points = [start[0] - distance, start[1]]
  } else if (angle >= -157.5 && angle <= -112.5) {
    lineAngle = -135
    radian = (-135 * Math.PI) / 180
    points = [start[0] + Math.sin(radian) * distance, start[1] - Math.cos(radian) * distance]
  } else if (angle >= -112.5 && angle <= -67.5) {
    lineAngle = -90
    points = [start[0], start[1] + distance]
  } else if (angle >= -67.5 && angle <= -22.5) {
    lineAngle = -45
    radian = (-45 * Math.PI) / 180
    points = [start[0] - Math.sin(radian) * distance, start[1] + Math.cos(radian) * distance]
  }
  return { points, lineAngle }
}

const getAnglePoints = (start: number[], angle: number, distance: number) => {
  let radian = 0
  let points = start
  if (angle < -180) angle += 360
  if (angle === 0) {
    points = start.concat([start[0] + distance, start[1]])
  } else if (angle > 0 && angle < 90) {
    radian = (angle * Math.PI) / 180
    points = start.concat([
      start[0] + Math.cos(radian) * distance,
      start[1] - Math.sin(radian) * distance
    ])
  } else if (angle === 90) {
    points = start.concat([start[0] + distance, start[1] - distance])
  } else if (angle > 90 && angle < 180) {
    radian = (angle * Math.PI) / 180
    points = start.concat([
      start[0] + Math.cos(radian) * distance,
      start[1] - Math.sin(radian) * distance
    ])
  } else if (angle === 180 || angle === -180) {
    points = start.concat([start[0] - distance, start[1]])
  } else if (angle > -180 && angle < -90) {
    radian = (angle * Math.PI) / 180
    points = start.concat([
      start[0] + Math.cos(radian) * distance,
      start[1] - Math.sin(radian) * distance
    ])
  } else if (angle === -90) {
    points = start.concat([start[0] - distance, start[1] + distance])
  } else if (angle > -90 && angle < 0) {
    radian = (angle * Math.PI) / 180
    points = start.concat([
      start[0] + Math.cos(radian) * distance,
      start[1] - Math.sin(radian) * distance
    ])
  }
  return points
}

const getColor = (color: 'BLK' | 'YLW' | 'RAL7035' | 'RAL5017' | 'RAL3000' | 'RAL9016' = 'BLK') => {
  switch (color) {
    case 'BLK':
      return new Color3(0, 0, 0)
    case 'YLW':
      return new Color3(0.95, 1, 0.11)
    case 'RAL7035':
      return new Color3(0.58, 0.58, 0.58)
    case 'RAL5017':
      return new Color3(0.13, 0, 0.93)
    case 'RAL3000':
      return new Color3(0.93, 0.05, 0.07)
    case 'RAL9016':
      return new Color3(1, 1, 1)
    default:
      return new Color3(0.8, 0.8, 0)
  }
}

const getFenceColor = (
  color: 'BLK' | 'YLW' | 'RAL7035' | 'RAL5017' | 'RAL3000' | 'RAL9016' = 'BLK'
) => {
  switch (color) {
    case 'BLK':
      return fenceBlackPic
    case 'YLW':
      return fenceYellowPic
    case 'RAL7035':
      return fenceGreyPic
    case 'RAL5017':
      return fenceBluePic
    case 'RAL3000':
      return fenceRedPic
    case 'RAL9016':
      return fenceWhitePic
    default:
      return fenceBluePic
  }
}

const createPillar = (
  x: number,
  z: number,
  angle: number,
  height: number,
  color: string,
  scale: number,
  scene: Scene
) => {
  const columnColor = new StandardMaterial('columnColor', scene)
  columnColor.diffuseColor = getColor(color)
  // 立柱实体

  const columnSingle = MeshBuilder.CreateBox('column_single', {})
  columnSingle.scaling = new Vector3(6 / scale, height / scale, 6 / scale)
  columnSingle.position.x = x
  columnSingle.position.z = z
  columnSingle.position.y = height / (scale * 2)
  columnSingle.material = columnColor

  const mesh = MeshBuilder.CreateBox('box', {}, scene)
  const pillarMaterial = new StandardMaterial('pillarMaterial', scene) // 参数1 材质 name，参数2 传入 scene
  pillarMaterial.diffuseColor = new Color3(0, 0, 0)
  mesh.scaling = new Vector3(15 / scale, 5 / scale, 15 / scale)
  mesh.material = pillarMaterial
  mesh.position.x = x
  mesh.position.y = 2.5 / scale
  mesh.position.z = z
}

const createFence = (
  x: number,
  z: number,
  angle: number,
  width: number,
  height: number,
  color: string,
  scale: number,
  scene: Scene
) => {
  const frameColor = new StandardMaterial('fenceMaterial', scene) // 参数1 材质 name，参数2 传入 scene
  frameColor.diffuseColor = getColor(color)
  const pos = getAnglePoints([x, z], angle - 180, 3 / scale)

  // fence.material = frameColor
  const frameData = [
    new Vector3(0.0, 0, 0.0),
    new Vector3(0.0, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, 0.0)
  ]
  // 网片边框2D掏网孔
  const holes = []
  holes[0] = [
    new Vector3(2 / scale, 0, 2 / scale),
    new Vector3(2 / scale, 0, (height / 2 - 1.5) / scale),
    new Vector3((width - 2) / scale, 0, (height / 2 - 1.5) / scale),
    new Vector3((width - 2) / scale, 0, 2 / scale)
  ]
  holes[1] = [
    new Vector3(2 / scale, 0, (height / 2 + 1.5) / scale),
    new Vector3(2 / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, (height / 2 + 1.5) / scale)
  ]

  // 网片闭合面3D挤出
  const windowW10 = MeshBuilder.ExtrudePolygon(
    'windowW10',
    {
      shape: frameData,
      holes,
      depth: 3 / scale,
      sideOrientation: Mesh.DOUBLESIDE
    },
    scene,
    earcut
  )
  windowW10.rotation.x = -Math.PI / 2
  windowW10.rotation.y = (angle * Math.PI) / 180
  windowW10.material = frameColor
  windowW10.position.y = 20 / scale
  windowW10.position.x = pos[2]
  windowW10.position.z = pos[3]

  // 网片孔内平面贴网格图

  const mat = new StandardMaterial('', scene)
  mat.diffuseTexture = new Texture(getFenceColor(color), scene)
  // mat.diffuseColor = new Color3(0.1, 0.1, 0.1)
  // mat.specularColor = new Color3(1, 1, 1)
  // mat.emissiveTexture = new Texture(fenceRedPic, scene)
  mat.opacityTexture = new Texture(getFenceColor(color), scene)
  // mat.opacityTexture.hasAlpha = true
  // mat.diffuseTexture.hasAlpha = true
  // mat.emissiveTexture.hasAlpha = true

  const plane = MeshBuilder.CreateTiledPlane(
    'fence',
    {
      pattern: Mesh.FLIP_TILE,
      alignVertical: Mesh.CENTER,
      alignHorizontal: Mesh.CENTER,
      frontUVs: new Vector4(0, 0, 2, 2),
      backUVs: new Vector4(0, 0, 2, 2),
      height: height / scale,
      width: (width - 0.2) / scale,
      sideOrientation: Mesh.DOUBLESIDE,
      tileSize: 3,
      tileWidth: 1
    },
    scene
  )
  const fixPosition = fixRadian([pos[2], pos[3]], angle, width / 2 / scale)
  plane.material = mat
  plane.rotation.y = (angle * Math.PI) / 180
  plane.position.y = (height / 2 + 23) / scale
  plane.position.x = fixPosition.points[0]
  plane.position.z = fixPosition.points[1]
}

const createDoor = (
  x: number,
  z: number,
  angle: number,
  width: number,
  height: number,
  color: string,
  direction: string,
  scale: number,
  scene: Scene
) => {
  const frameColor = new StandardMaterial('frameColor', scene)
  frameColor.diffuseColor = getColor(color)
  const pos = getAnglePoints([x, z], angle - 180, 3 / scale)

  const frameDoor = [
    new Vector3(0.0, 0, 0.0),
    new Vector3(0.0, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, 0.0)
  ]

  // 网片边框2D掏网孔
  const doorHoles = []
  doorHoles[0] = [
    new Vector3(2 / scale, 0, 2 / scale),
    new Vector3(2 / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, 2 / scale)
  ]

  // 网片闭合面3D挤出
  const doorW10 = MeshBuilder.ExtrudePolygon(
    'doorW10',
    {
      shape: frameDoor,
      holes: doorHoles,
      depth: 3 / scale,
      sideOrientation: Mesh.DOUBLESIDE
    },
    scene,
    earcut
  )
  doorW10.rotation.x = -Math.PI / 2
  doorW10.rotation.y = (angle * Math.PI) / 180
  doorW10.material = frameColor
  doorW10.position.y = 20 / scale
  doorW10.position.x = pos[2]
  doorW10.position.z = pos[3]
  // createJLMDoor(x, z, angle, width, height, frameColor, direction, scale, scene)
  let startPos = getAnglePoints([pos[2], pos[3]], 0, width / scale)
  if (direction === 'LEFT') {
    angle -= 20
    startPos = [x, z, x, z]
  } else {
    angle -= 160
    startPos = getAnglePoints([pos[2], pos[3]], 0, width / scale)
  }

  // 构建门网外边框2D轮廓
  const frameData = [
    new Vector3(0.0, 0, 0.0),
    new Vector3(0.0, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, 0.0)
  ]

  // 网片边框2D掏网孔
  const holes = []
  holes[0] = [
    new Vector3(2 / scale, 0, 2 / scale),
    new Vector3(2 / scale, 0, (height / 2 - 1.5) / scale),
    new Vector3((width - 2) / scale, 0, (height / 2 - 1.5) / scale),
    new Vector3((width - 2) / scale, 0, 2 / scale)
  ]
  holes[1] = [
    new Vector3(2 / scale, 0, (height / 2 + 1.5) / scale),
    new Vector3(2 / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, (height / 2 + 1.5) / scale)
  ]

  // 网片闭合面3D挤出
  const windowW10 = MeshBuilder.ExtrudePolygon(
    'windowW10',
    {
      shape: frameData,
      holes,
      depth: 3 / scale,
      sideOrientation: Mesh.DOUBLESIDE
    },
    scene,
    earcut
  )
  windowW10.rotation.x = -Math.PI / 2
  windowW10.rotation.y = (angle * Math.PI) / 180
  windowW10.material = frameColor
  windowW10.position.y = 20 / scale
  windowW10.position.x = startPos[2]
  windowW10.position.z = startPos[3]

  const plane = MeshBuilder.CreateTiledPlane(
    'fence',
    {
      pattern: Mesh.FLIP_TILE,
      alignVertical: Mesh.CENTER,
      alignHorizontal: Mesh.CENTER,
      frontUVs: new Vector4(0, 0, 2, 2),
      backUVs: new Vector4(0, 0, 2, 2),
      height: height / scale,
      width: (width - 0.2) / scale,
      sideOrientation: Mesh.DOUBLESIDE,
      tileSize: 30 / scale,
      tileWidth: 10 / scale
    },
    scene
  )
  const mat = new StandardMaterial('', scene)
  mat.diffuseTexture = new Texture(getFenceColor(color), scene)
  mat.opacityTexture = new Texture(getFenceColor(color), scene)

  let fixPosition = getAnglePoints([startPos[2], startPos[3]], angle, width / 2 / scale)
  plane.material = mat
  plane.rotation.y = (angle * Math.PI) / 180
  plane.position.y = (height / 2 + 22) / scale
  plane.position.x = fixPosition[2]
  plane.position.z = fixPosition[3]

  const wheelMaterial = new StandardMaterial('wheel_mat', scene)
  const wheelTexture = new Texture(wheelPic, scene)
  wheelMaterial.diffuseTexture = wheelTexture
  wheelMaterial.diffuseTexture.hasAlpha = true

  const faceColors = []
  faceColors[1] = new Color4(0, 0, 0, 0)
  // set texture for flat face of wheel
  const faceUV = []
  faceUV[0] = new Vector4(0, 0, 1, 1)
  faceUV[1] = new Vector4(0, 0, 1, 1)

  fixPosition = getAnglePoints([startPos[2], startPos[3]], angle, (width - 13) / scale)
  // const wheel = MeshBuilder.CreateCylinder(
  //   'wheel',
  //   { diameter: 14 / scale, height: 5 / scale, tessellation: 24, faceColors, faceUV },
  //   scene
  // )
  const wheel = MeshBuilder.CreatePlane('wheel', {
    height: 80 / scale,
    width: 128 / scale,
    backUVs: new Vector4(0, 0, 1, 1),
    frontUVs: new Vector4(0, 0, 1, 1),
    sideOrientation: Mesh.DOUBLESIDE
  })
  wheel.material = wheelMaterial

  wheel.rotation.y = (angle * Math.PI) / 180
  wheel.position.x = fixPosition[2]
  wheel.position.y = 25 / scale
  wheel.position.z = fixPosition[3]

  // rotate wheel so tread in xz plane
  // wheel.rotation.x = Math.PI / 2
  // wheel.rotation.z = (angle * Math.PI) / 180
  // wheel.position.x = fixPosition[2]
  // wheel.position.y = 7 / scale
  // wheel.position.z = fixPosition[3]

  /** *-----------------门锁 ------------------------** */
  const bLock = new StandardMaterial('', scene)
  bLock.diffuseTexture = new Texture(bLockPic, scene)
  bLock.diffuseTexture.hasAlpha = true

  const bLockerPlane = MeshBuilder.CreatePlane('blocker_plane', {
    height: 20 / scale,
    width: 40 / scale,
    backUVs: new Vector4(0.5, 0, 1, 1),
    frontUVs: new Vector4(0, 0, 0.5, 1),
    sideOrientation: Mesh.DOUBLESIDE
  })
  fixPosition = getAnglePoints([startPos[2], startPos[3]], angle, (width - 5) / scale)

  bLockerPlane.rotation.y = (angle * Math.PI) / 180
  bLockerPlane.material = bLock
  bLockerPlane.position.x = fixPosition[2]
  bLockerPlane.position.y = (height + 20) / 2 / scale
  bLockerPlane.position.z = fixPosition[3]
  /** *-----------------门锁完成------------------------** */

  // mat.diffuseTexture.hasAlpha = true
}

const createPymDoor = (
  x: number,
  z: number,
  angle: number,
  width: number,
  height: number,
  color: string,
  direction: string,
  scale: number,
  scene: Scene
) => {
  const frameColor = new StandardMaterial('fenceMaterial', scene) // 参数1 材质 name，参数2 传入 scene
  frameColor.diffuseColor = getColor(color)
  let pos = getAnglePoints([x, z], angle - 180, 3 / scale)

  // fence.material = frameColor
  const frameData = [
    new Vector3(0.0, 0, 0.0),
    new Vector3(0.0, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, (height + 5) / scale),
    new Vector3(width / scale, 0, 0.0)
  ]
  // 网片边框2D掏网孔
  const holes = []
  holes[0] = [
    new Vector3(2 / scale, 0, 2 / scale),
    new Vector3(2 / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, (height + 3) / scale),
    new Vector3((width - 2) / scale, 0, 2 / scale)
  ]

  // 网片闭合面3D挤出
  const windowW10 = MeshBuilder.ExtrudePolygon(
    'windowW10',
    {
      shape: frameData,
      holes,
      depth: 3 / scale,
      sideOrientation: Mesh.DOUBLESIDE
    },
    scene,
    earcut
  )
  windowW10.rotation.x = -Math.PI / 2
  windowW10.rotation.y = (angle * Math.PI) / 180
  windowW10.material = frameColor
  windowW10.position.y = 20 / scale
  windowW10.position.x = pos[2]
  windowW10.position.z = pos[3]

  const bLock = new StandardMaterial('', scene)
  bLock.diffuseTexture = new Texture(bLockPic, scene)
  bLock.diffuseTexture.hasAlpha = true

  const bLockerPlane = MeshBuilder.CreatePlane('blocker_plane', {
    height: 20 / scale,
    width: 40 / scale,
    backUVs: new Vector4(0.5, 0, 1, 1),
    frontUVs: new Vector4(0, 0, 0.5, 1),
    sideOrientation: Mesh.DOUBLESIDE
  })
  let fixPosition = fixRadian([x, z], angle, width / 5 / scale)

  if (direction === 'LEFT') {
    fixPosition = fixRadian([x, z], angle, (width / 1.2 - 5) / scale)
    createFence(x, z, angle, width / 2, height, color, scale, scene)
    const posDoor = fixRadian([x, z], angle, width / 3 / scale)
    createFence(posDoor.points[0], posDoor.points[1], angle, width / 2, height, color, scale, scene)
    bLockerPlane.rotation.y = (angle * Math.PI) / 180
  } else {
    let posDoor = fixRadian([x, z], angle, width / 5 / scale)
    createFence(posDoor.points[0], posDoor.points[1], angle, width / 2, height, color, scale, scene)
    posDoor = fixRadian([x, z], angle, width / 2 / scale)
    createFence(posDoor.points[0], posDoor.points[1], angle, width / 2, height, color, scale, scene)
    bLockerPlane.rotation.y = ((angle - 180) * Math.PI) / 180
  }

  bLockerPlane.material = bLock
  bLockerPlane.position.x = fixPosition.points[0]
  bLockerPlane.position.y = (height + 20) / 2 / scale
  bLockerPlane.position.z = fixPosition.points[1]
}
export default { createPillar, createFence, createDoor, createPymDoor }
